from datetime import datetime, timedelta, timezone
from typing import Optional, Union
import re


def utc_now() -> datetime:
    """获取当前UTC时间"""
    return datetime.now(timezone.utc)


def local_now() -> datetime:
    """获取当前本地时间"""
    return datetime.now()


def to_utc(dt: datetime) -> datetime:
    """转换为UTC时间"""
    if dt.tzinfo is None:
        # 假设是本地时间
        dt = dt.replace(tzinfo=timezone.utc)
    return dt.astimezone(timezone.utc)


def to_local(dt: datetime, tz: timezone = None) -> datetime:
    """转换为本地时间"""
    if tz is None:
        tz = datetime.now().astimezone().tzinfo
    
    if dt.tzinfo is None:
        dt = dt.replace(tzinfo=timezone.utc)
    
    return dt.astimezone(tz)


def format_datetime(dt: Optional[datetime], fmt: str = "%Y-%m-%d %H:%M:%S") -> Optional[str]:
    """格式化日期时间"""
    if dt is None:
        return None
    return dt.strftime(fmt)


def parse_datetime(dt_str: str, fmt: str = "%Y-%m-%d %H:%M:%S") -> Optional[datetime]:
    """解析日期时间字符串"""
    try:
        return datetime.strptime(dt_str, fmt)
    except ValueError:
        return None


def iso_format(dt: datetime) -> str:
    """ISO格式化日期时间"""
    return dt.isoformat() + "Z" if dt.tzinfo is None else dt.isoformat()


def parse_iso(dt_str: str) -> Optional[datetime]:
    """解析ISO格式日期时间"""
    try:
        # 移除结尾的Z
        if dt_str.endswith('Z'):
            dt_str = dt_str[:-1] + '+00:00'
        
        return datetime.fromisoformat(dt_str)
    except ValueError:
        return None


def add_days(dt: datetime, days: int) -> datetime:
    """日期加天数"""
    return dt + timedelta(days=days)


def add_hours(dt: datetime, hours: int) -> datetime:
    """日期加小时数"""
    return dt + timedelta(hours=hours)


def add_minutes(dt: datetime, minutes: int) -> datetime:
    """日期加分钟数"""
    return dt + timedelta(minutes=minutes)


def diff_days(dt1: datetime, dt2: datetime) -> int:
    """计算两个日期的天数差"""
    return (dt1 - dt2).days


def diff_hours(dt1: datetime, dt2: datetime) -> int:
    """计算两个日期的小时差"""
    return int((dt1 - dt2).total_seconds() / 3600)


def diff_minutes(dt1: datetime, dt2: datetime) -> int:
    """计算两个日期的分钟差"""
    return int((dt1 - dt2).total_seconds() / 60)


def is_today(dt: datetime) -> bool:
    """判断是否是今天"""
    today = datetime.now().date()
    return dt.date() == today


def is_this_week(dt: datetime) -> bool:
    """判断是否是本周"""
    today = datetime.now()
    start_of_week = today - timedelta(days=today.weekday())
    end_of_week = start_of_week + timedelta(days=7)
    
    return start_of_week.date() <= dt.date() < end_of_week.date()


def is_this_month(dt: datetime) -> bool:
    """判断是否是本月"""
    today = datetime.now()
    return dt.year == today.year and dt.month == today.month


def start_of_day(dt: datetime) -> datetime:
    """获取一天的开始时间"""
    return dt.replace(hour=0, minute=0, second=0, microsecond=0)


def end_of_day(dt: datetime) -> datetime:
    """获取一天的结束时间"""
    return dt.replace(hour=23, minute=59, second=59, microsecond=999999)


def start_of_month(dt: datetime) -> datetime:
    """获取月初时间"""
    return dt.replace(day=1, hour=0, minute=0, second=0, microsecond=0)


def end_of_month(dt: datetime) -> datetime:
    """获取月末时间"""
    next_month = dt.replace(day=28) + timedelta(days=4)
    return next_month - timedelta(days=next_month.day)


def humanize_datetime(dt: datetime) -> str:
    """人性化显示日期时间"""
    now = datetime.now()
    diff = now - dt
    
    if diff.days > 0:
        if diff.days == 1:
            return "昨天"
        elif diff.days < 7:
            return f"{diff.days}天前"
        elif diff.days < 30:
            weeks = diff.days // 7
            return f"{weeks}周前"
        elif diff.days < 365:
            months = diff.days // 30
            return f"{months}个月前"
        else:
            years = diff.days // 365
            return f"{years}年前"
    
    elif diff.seconds > 0:
        if diff.seconds < 60:
            return "刚刚"
        elif diff.seconds < 3600:
            minutes = diff.seconds // 60
            return f"{minutes}分钟前"
        else:
            hours = diff.seconds // 3600
            return f"{hours}小时前"
    
    else:
        return "刚刚"


def get_week_range(dt: datetime = None) -> tuple[datetime, datetime]:
    """获取指定日期所在周的起止时间"""
    if dt is None:
        dt = datetime.now()
    
    start = dt - timedelta(days=dt.weekday())
    end = start + timedelta(days=6)
    
    return start_of_day(start), end_of_day(end)


def get_month_range(dt: datetime = None) -> tuple[datetime, datetime]:
    """获取指定日期所在月的起止时间"""
    if dt is None:
        dt = datetime.now()
    
    start = start_of_month(dt)
    end = end_of_month(dt)
    
    return start, end_of_day(end)


def get_quarter_range(dt: datetime = None) -> tuple[datetime, datetime]:
    """获取指定日期所在季度的起止时间"""
    if dt is None:
        dt = datetime.now()
    
    quarter = (dt.month - 1) // 3 + 1
    start_month = (quarter - 1) * 3 + 1
    
    start = dt.replace(month=start_month, day=1, hour=0, minute=0, second=0, microsecond=0)
    end_month = start_month + 2
    end = dt.replace(month=end_month, day=1) + timedelta(days=32)
    end = end.replace(day=1) - timedelta(days=1)
    end = end_of_day(end)
    
    return start, end


def get_year_range(dt: datetime = None) -> tuple[datetime, datetime]:
    """获取指定日期所在年的起止时间"""
    if dt is None:
        dt = datetime.now()
    
    start = dt.replace(month=1, day=1, hour=0, minute=0, second=0, microsecond=0)
    end = dt.replace(month=12, day=31, hour=23, minute=59, second=59, microsecond=999999)
    
    return start, end